#include <func.h>

int udp_bind(const char* port)
{
    struct addrinfo hints;
    bzero(&hints, sizeof(hints));
    hints.ai_flags = AI_PASSIVE;    // 通配符地址
    hints.ai_family = AF_INET;      // IPv4
    hints.ai_socktype = SOCK_DGRAM; // UDP

    struct addrinfo *result, *p;
    int err = getaddrinfo(NULL, port, &hints, &result);
    if (err) {
        fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err));
        exit(1);
    }

    // 遍历地址信息，绑定套接字地址
    int sockfd;
    for (p = result; p != NULL; p = p->ai_next) {
        // 创建主动套接字
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            continue;
        }
        // 绑定地址
        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            continue;
        }
        break;
    }

    // 释放地址信息
    freeaddrinfo(result);
    if (p == NULL) {
        return -1;
    }
    return sockfd;
}

int main(int argc, char* argv[])
{
    // ./daytime_server port 
    if (argc != 2) {
        error(1, 0, "Usage: %s port", argv[0]);
    }

    int sockfd = udp_bind(argv[1]);
    if (sockfd == -1) {
        error(1, errno, "udp_bind()");
    }
    
    struct sockaddr_storage ss;
    socklen_t addrlen = sizeof(ss);

    char daytime[20];
    for(;;) {
        // 接收请求
        recvfrom(sockfd, NULL, 0, 0, (struct sockaddr*)&ss, &addrlen);
        // 获取当前时间
        time_t timestamp = time(NULL);
        // 转换成 broken-down time 
        struct tm* bt = localtime(&timestamp);
        // 格式化 broken-down time
        int n = strftime(daytime, 20, "%4Y-%2m-%2d %2H:%2M:%2S", bt);
        sendto(sockfd, daytime, n, 0, (struct sockaddr*)&ss, addrlen);
    }

    return 0;
}

